home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 1 / CU Amiga Magazine CD-ROM Special Edition (1995)(EMAP Images)(GB)[Issue 1995-11].iso / Aminet / comm / tcp / ATCP_sdk_40_gc.lha / AmiTCP-4.0-gcc / src / rpclib / xdr.c < prev   
C/C++ Source or Header  |  1994-09-30  |  10KB  |  551 lines

  1. /*
  2.  *      $Id: xdr.c,v 4.2 1994/09/29 23:48:50 jraja Exp $
  3.  *
  4.  *      Generic XDR routines implementation.
  5.  *
  6.  *      Copyright © 1994 AmiTCP/IP Group,
  7.  *                       Network Solutions Development Inc.
  8.  *                       All rights reserved. 
  9.  */
  10.  
  11. /* @(#)xdr.c    2.1 88/07/29 4.0 RPCSRC */
  12. #if !defined(lint) && defined(SCCSIDS)
  13. static char sccsid[] = "@(#)xdr.c 1.35 87/08/12";
  14. #endif
  15.  
  16. /*
  17.  * Copyright (C) 1986, Sun Microsystems, Inc.
  18.  *
  19.  * These are the "generic" xdr routines used to serialize and de-serialize
  20.  * most common data items.  See xdr.h for more info on the interface to
  21.  * xdr.
  22.  */
  23.  
  24. #include <sys/param.h>
  25. #include <stdio.h>
  26. #include <rpc/types.h>
  27. #include <rpc/xdr.h>
  28.  
  29. #include <limits.h>
  30.  
  31. /*
  32.  * constants specific to the xdr "protocol"
  33.  */
  34. #define XDR_FALSE    ((long) 0)
  35. #define XDR_TRUE    ((long) 1)
  36.  
  37. /*
  38.  * for unit alignment
  39.  */
  40. static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
  41.  
  42. /*
  43.  * Free a data structure using XDR
  44.  * Not a filter, but a convenient utility nonetheless
  45.  */
  46. void
  47. xdr_free(xdrproc_t proc, void *objp)
  48. {
  49.     XDR x;
  50.     
  51.     x.x_op = XDR_FREE;
  52.     (*proc)(&x, objp);
  53. }
  54.  
  55. /*
  56.  * XDR nothing
  57.  */
  58. bool_t XDRFUN
  59. xdr_void(XDR * xdrs, void *dummy)
  60. {
  61.     return (TRUE);
  62. }
  63.  
  64. /*
  65.  * XDR integers
  66.  */
  67. bool_t XDRFUN
  68. xdr_int(xdrs, ip)
  69.     XDR *xdrs;
  70.     int *ip;
  71. {
  72.  
  73. #ifdef lint
  74.     (void) (xdr_short(xdrs, (short *)ip));
  75.     return (xdr_long(xdrs, (long *)ip));
  76. #else
  77.     if (sizeof (int) == sizeof (long)) {
  78.         return (xdr_long(xdrs, (long *)ip));
  79.     } else {
  80.         return (xdr_short(xdrs, (short *)ip));
  81.     }
  82. #endif
  83. }
  84.  
  85. /*
  86.  * XDR unsigned integers
  87.  */
  88. bool_t XDRFUN
  89. xdr_u_int(xdrs, up)
  90.     XDR *xdrs;
  91.     u_int *up;
  92. {
  93.  
  94. #ifdef lint
  95.     (void) (xdr_u_short(xdrs, (u_short *)up));
  96.     return (xdr_u_long(xdrs, (u_long *)up));
  97. #else
  98.     if (sizeof (u_int) == sizeof (u_long)) {
  99.         return (xdr_u_long(xdrs, (u_long *)up));
  100.     } else {
  101.         return (xdr_u_short(xdrs, (u_short *)up));
  102.     }
  103. #endif
  104. }
  105.  
  106. /*
  107.  * XDR long integers
  108.  * same as xdr_u_long - open coded to save a proc call!
  109.  */
  110. bool_t XDRFUN
  111. xdr_long(xdrs, lp)
  112.     register XDR *xdrs;
  113.     long *lp;
  114. {
  115.  
  116.     if (xdrs->x_op == XDR_ENCODE)
  117.         return (XDR_PUTLONG(xdrs, lp));
  118.  
  119.     if (xdrs->x_op == XDR_DECODE)
  120.         return (XDR_GETLONG(xdrs, lp));
  121.  
  122.     if (xdrs->x_op == XDR_FREE)
  123.         return (TRUE);
  124.  
  125.     return (FALSE);
  126. }
  127.  
  128. /*
  129.  * XDR unsigned long integers
  130.  * same as xdr_long - open coded to save a proc call!
  131.  */
  132. bool_t XDRFUN
  133. xdr_u_long(xdrs, ulp)
  134.     register XDR *xdrs;
  135.     u_long *ulp;
  136. {
  137.  
  138.     if (xdrs->x_op == XDR_DECODE)
  139.         return (XDR_GETLONG(xdrs, (long *)ulp));
  140.     if (xdrs->x_op == XDR_ENCODE)
  141.         return (XDR_PUTLONG(xdrs, (long *)ulp));
  142.     if (xdrs->x_op == XDR_FREE)
  143.         return (TRUE);
  144.     return (FALSE);
  145. }
  146.  
  147. /*
  148.  * XDR short integers
  149.  */
  150. bool_t XDRFUN
  151. xdr_short(xdrs, sp)
  152.     register XDR *xdrs;
  153.     short *sp;
  154. {
  155.     long l;
  156.  
  157.     switch (xdrs->x_op) {
  158.  
  159.     case XDR_ENCODE:
  160.         l = (long) *sp;
  161.         return (XDR_PUTLONG(xdrs, &l));
  162.  
  163.     case XDR_DECODE:
  164.         if (!XDR_GETLONG(xdrs, &l)) {
  165.             return (FALSE);
  166.         }
  167.         *sp = (short) l;
  168.         return (TRUE);
  169.  
  170.     case XDR_FREE:
  171.         return (TRUE);
  172.     }
  173.     return (FALSE);
  174. }
  175.  
  176. /*
  177.  * XDR unsigned short integers
  178.  */
  179. bool_t XDRFUN
  180. xdr_u_short(xdrs, usp)
  181.     register XDR *xdrs;
  182.     u_short *usp;
  183. {
  184.     u_long l;
  185.  
  186.     switch (xdrs->x_op) {
  187.  
  188.     case XDR_ENCODE:
  189.         l = (u_long) *usp;
  190.         return (XDR_PUTLONG(xdrs, (long *)&l));
  191.  
  192.     case XDR_DECODE:
  193.         if (!XDR_GETLONG(xdrs, (long *)&l)) {
  194.             return (FALSE);
  195.         }
  196.         *usp = (u_short) l;
  197.         return (TRUE);
  198.  
  199.     case XDR_FREE:
  200.         return (TRUE);
  201.     }
  202.     return (FALSE);
  203. }
  204.  
  205.  
  206. /*
  207.  * XDR a char
  208.  */
  209. bool_t XDRFUN
  210. xdr_char(xdrs, cp)
  211.     XDR *xdrs;
  212.     char *cp;
  213. {
  214.     int i;
  215.  
  216.     i = (*cp);
  217.     if (!xdr_int(xdrs, &i)) {
  218.         return (FALSE);
  219.     }
  220.     *cp = i;
  221.     return (TRUE);
  222. }
  223.  
  224. /*
  225.  * XDR an unsigned char
  226.  */
  227. bool_t XDRFUN
  228. xdr_u_char(xdrs, cp)
  229.     XDR *xdrs;
  230.     u_char *cp;
  231. {
  232.     u_int u;
  233.  
  234.     u = (*cp);
  235.     if (!xdr_u_int(xdrs, &u)) {
  236.         return (FALSE);
  237.     }
  238.     *cp = u;
  239.     return (TRUE);
  240. }
  241.  
  242. /*
  243.  * XDR booleans
  244.  */
  245. bool_t XDRFUN
  246. xdr_bool(xdrs, bp)
  247.     register XDR *xdrs;
  248.     bool_t *bp;
  249. {
  250.     long lb;
  251.  
  252.     switch (xdrs->x_op) {
  253.  
  254.     case XDR_ENCODE:
  255.         lb = *bp ? XDR_TRUE : XDR_FALSE;
  256.         return (XDR_PUTLONG(xdrs, &lb));
  257.  
  258.     case XDR_DECODE:
  259.         if (!XDR_GETLONG(xdrs, &lb)) {
  260.             return (FALSE);
  261.         }
  262.         *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
  263.         return (TRUE);
  264.  
  265.     case XDR_FREE:
  266.         return (TRUE);
  267.     }
  268.     return (FALSE);
  269. }
  270.  
  271. /*
  272.  * XDR enumerations
  273.  */
  274. bool_t XDRFUN
  275. xdr_enum(xdrs, ep)
  276.     XDR *xdrs;
  277.     enum_t *ep;
  278. {
  279. #ifndef lint
  280.     enum sizecheck { SIZEVAL };    /* used to find the size of an enum */
  281.  
  282.     /*
  283.      * enums are treated as ints
  284.      */
  285.     if (sizeof (enum sizecheck) == sizeof (long)) {
  286.         return (xdr_long(xdrs, (long *)ep));
  287.     } else if (sizeof (enum sizecheck) == sizeof (short)) {
  288.         return (xdr_short(xdrs, (short *)ep));
  289.     } else {
  290.         return (FALSE);
  291.     }
  292. #else
  293.     (void) (xdr_short(xdrs, (short *)ep));
  294.     return (xdr_long(xdrs, (long *)ep));
  295. #endif
  296. }
  297.  
  298. /*
  299.  * XDR opaque data
  300.  * Allows the specification of a fixed size sequence of opaque bytes.
  301.  * cp points to the opaque object and cnt gives the byte length.
  302.  */
  303. bool_t XDRFUN
  304. xdr_opaque(xdrs, cp, cnt)
  305.     register XDR *xdrs;
  306.     caddr_t cp;
  307.     register u_int cnt;
  308. {
  309.     register u_int rndup;
  310.     static char crud[BYTES_PER_XDR_UNIT];
  311.  
  312.     /*
  313.      * if no data we are done
  314.      */
  315.     if (cnt == 0)
  316.         return (TRUE);
  317.  
  318.     /*
  319.      * round byte count to full xdr units
  320.      */
  321.     rndup = cnt % BYTES_PER_XDR_UNIT;
  322.     if (rndup > 0)
  323.         rndup = BYTES_PER_XDR_UNIT - rndup;
  324.  
  325.     if (xdrs->x_op == XDR_DECODE) {
  326.         if (!XDR_GETBYTES(xdrs, cp, cnt)) {
  327.             return (FALSE);
  328.         }
  329.         if (rndup == 0)
  330.             return (TRUE);
  331.         return (XDR_GETBYTES(xdrs, crud, rndup));
  332.     }
  333.  
  334.     if (xdrs->x_op == XDR_ENCODE) {
  335.         if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
  336.             return (FALSE);
  337.         }
  338.         if (rndup == 0)
  339.             return (TRUE);
  340.         return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
  341.     }
  342.  
  343.     if (xdrs->x_op == XDR_FREE) {
  344.         return (TRUE);
  345.     }
  346.  
  347.     return (FALSE);
  348. }
  349.  
  350. /*
  351.  * XDR counted bytes
  352.  * *cpp is a pointer to the bytes, *sizep is the count.
  353.  * If *cpp is NULL maxsize bytes are allocated
  354.  */
  355. bool_t XDRFUN
  356. xdr_bytes(xdrs, cpp, sizep, maxsize)
  357.     register XDR *xdrs;
  358.     char **cpp;
  359.     register u_int *sizep;
  360.     u_int maxsize;
  361. {
  362.     register char *sp = *cpp;  /* sp is the actual string pointer */
  363.     register u_int nodesize;
  364.  
  365.     /*
  366.      * first deal with the length since xdr bytes are counted
  367.      */
  368.     if (! xdr_u_int(xdrs, sizep)) {
  369.         return (FALSE);
  370.     }
  371.     nodesize = *sizep;
  372.     if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
  373.         return (FALSE);
  374.     }
  375.  
  376.     /*
  377.      * now deal with the actual bytes
  378.      */
  379.     switch (xdrs->x_op) {
  380.  
  381.     case XDR_DECODE:
  382.         if (nodesize == 0) {
  383.             return (TRUE);
  384.         }
  385.         if (sp == NULL) {
  386.             *cpp = sp = (char *)mem_alloc(nodesize);
  387.         }
  388.         if (sp == NULL) {
  389.             (void) fprintf(stderr, "xdr_bytes: out of memory\n");
  390.             return (FALSE);
  391.         }
  392.         /* fall into ... */
  393.  
  394.     case XDR_ENCODE:
  395.         return (xdr_opaque(xdrs, sp, nodesize));
  396.  
  397.     case XDR_FREE:
  398.         if (sp != NULL) {
  399.             mem_free(sp, nodesize);
  400.             *cpp = NULL;
  401.         }
  402.         return (TRUE);
  403.     }
  404.     return (FALSE);
  405. }
  406.  
  407. /*
  408.  * Implemented here due to commonality of the object.
  409.  */
  410. bool_t XDRFUN
  411. xdr_netobj(xdrs, np)
  412.     XDR *xdrs;
  413.     struct netobj *np;
  414. {
  415.  
  416.     return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
  417. }
  418.  
  419. /*
  420.  * XDR a descriminated union
  421.  * Support routine for discriminated unions.
  422.  * You create an array of xdrdiscrim structures, terminated with
  423.  * an entry with a null procedure pointer.  The routine gets
  424.  * the discriminant value and then searches the array of xdrdiscrims
  425.  * looking for that value.  It calls the procedure given in the xdrdiscrim
  426.  * to handle the discriminant.  If there is no specific routine a default
  427.  * routine may be called.
  428.  * If there is no specific or default routine an error is returned.
  429.  */
  430. bool_t XDRFUN
  431. xdr_union(xdrs, dscmp, unp, choices, dfault)
  432.     register XDR *xdrs;
  433.     enum_t *dscmp;        /* enum to decide which arm to work on */
  434.     char *unp;        /* the union itself */
  435.     struct xdr_discrim *choices;    /* [value, xdr proc] for each arm */
  436.     xdrproc_t dfault;    /* default xdr routine */
  437. {
  438.     register enum_t dscm;
  439.  
  440.     /*
  441.      * we deal with the discriminator;  it's an enum
  442.      */
  443.     if (! xdr_enum(xdrs, dscmp)) {
  444.         return (FALSE);
  445.     }
  446.     dscm = *dscmp;
  447.  
  448.     /*
  449.      * search choices for a value that matches the discriminator.
  450.      * if we find one, execute the xdr routine for that value.
  451.      */
  452.     for (; choices->proc != NULL_xdrproc_t; choices++) {
  453.         if (choices->value == dscm)
  454.             return ((*(xdr_string_t)(choices->proc))(xdrs, unp,
  455.                                  UINT_MAX));
  456.     }
  457.  
  458.     /*
  459.      * no match - execute the default xdr routine if there is one
  460.      */
  461.     return ((dfault == NULL_xdrproc_t) ? FALSE :
  462.         (*(xdr_string_t)dfault)(xdrs, unp, UINT_MAX));
  463. }
  464.  
  465.  
  466. /*
  467.  * Non-portable xdr primitives.
  468.  * Care should be taken when moving these routines to new architectures.
  469.  */
  470.  
  471.  
  472. /*
  473.  * XDR null terminated ASCII strings
  474.  * xdr_string deals with "C strings" - arrays of bytes that are
  475.  * terminated by a NULL character.  The parameter cpp references a
  476.  * pointer to storage; If the pointer is null, then the necessary
  477.  * storage is allocated.  The last parameter is the max allowed length
  478.  * of the string as specified by a protocol.
  479.  */
  480. bool_t XDRFUN
  481. xdr_string(xdrs, cpp, maxsize)
  482.     register XDR *xdrs;
  483.     char **cpp;
  484.     u_int maxsize;
  485. {
  486.     register char *sp = *cpp;  /* sp is the actual string pointer */
  487.     u_int size;
  488.     u_int nodesize;
  489.  
  490.     /*
  491.      * first deal with the length since xdr strings are counted-strings
  492.      */
  493.     switch (xdrs->x_op) {
  494.     case XDR_FREE:
  495.         if (sp == NULL) {
  496.             return(TRUE);    /* already free */
  497.         }
  498.         /* fall through... */
  499.     case XDR_ENCODE:
  500.         size = strlen(sp);
  501.         break;
  502.     }
  503.     if (! xdr_u_int(xdrs, &size)) {
  504.         return (FALSE);
  505.     }
  506.     if (size > maxsize) {
  507.         return (FALSE);
  508.     }
  509.     nodesize = size + 1;
  510.  
  511.     /*
  512.      * now deal with the actual bytes
  513.      */
  514.     switch (xdrs->x_op) {
  515.  
  516.     case XDR_DECODE:
  517.         if (nodesize == 0) {
  518.             return (TRUE);
  519.         }
  520.         if (sp == NULL)
  521.             *cpp = sp = (char *)mem_alloc(nodesize);
  522.         if (sp == NULL) {
  523.             (void) fprintf(stderr, "xdr_string: out of memory\n");
  524.             return (FALSE);
  525.         }
  526.         sp[size] = 0;
  527.         /* fall into ... */
  528.  
  529.     case XDR_ENCODE:
  530.         return (xdr_opaque(xdrs, sp, size));
  531.  
  532.     case XDR_FREE:
  533.         mem_free(sp, nodesize);
  534.         *cpp = NULL;
  535.         return (TRUE);
  536.     }
  537.     return (FALSE);
  538. }
  539.  
  540. /* 
  541.  * Wrapper for xdr_string that can be called directly from 
  542.  * routines like clnt_call
  543.  */
  544. bool_t XDRFUN
  545. xdr_wrapstring(xdrs, cpp)
  546.     XDR *xdrs;
  547.     char **cpp;
  548. {
  549.     return xdr_string(xdrs, cpp, UINT_MAX);
  550. }
  551.